﻿using System.Linq;
using BITS.Library.Linq.Helper;
using BITS.PreCompiler.CSharp.Syntax;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
using Roslyn.Services.Formatting;

namespace BITS.PreCompiler.CSharp.Semantic.Extensions
{
    public static partial class SemanticModelExtension
    {
        public static AliasSymbol GetDeclaredSymbol(this SemanticModel @this, Using @using)
        {
            var func = Infer.Func((UsingDirectiveSyntax x) => 
                x.Format(FormattingOptions.GetDefaultOptions()).GetFormattedRoot().ToFullString().Trim());

            var usingText = func(@using.GetSyntaxNode());

            var result = @this.SyntaxTree.GetRoot()
                .DescendantNodes()
                .OfType<UsingDirectiveSyntax>()
                .Single(x => func(x) == usingText);

            return @this.GetDeclaredSymbol(result);
        }

        public static NamedTypeSymbol GetDeclaredSymbol(this SemanticModel @this, Class @class)
        {
            var func = Infer.Func((ClassDeclarationSyntax x) =>
                x.Format(FormattingOptions.GetDefaultOptions()).GetFormattedRoot().ToFullString().Trim());

            var classText = func(@class.GetSyntaxNode());

            var result = @this.SyntaxTree.GetRoot()
                .DescendantNodes()
                .OfType<ClassDeclarationSyntax>()
                .Single(x => func(x) == classText);

            return @this.GetDeclaredSymbol(result);
        }

        public static MethodSymbol GetDeclaredSymbol(this SemanticModel @this, Method @method)
        {
            var func = Infer.Func((MethodDeclarationSyntax x) =>
                x.Format(FormattingOptions.GetDefaultOptions()).GetFormattedRoot().ToFullString().Trim());

            var methodText = func(@method.GetSyntaxNode());

            var result = @this.SyntaxTree.GetRoot()
                .DescendantNodes()
                .OfType<MethodDeclarationSyntax>()
                .Single(x => func(x) == methodText);

            return @this.GetDeclaredSymbol(result);
        }
    }
}
